#pragma once
#ifndef CLIB_STACK_NETIF_H
#define CLIB_STACK_NETIF_H

#include "clib_type.h"
#include "clib_ip.h"

#ifdef __cplusplus
extern "C" {
#endif


#define  NETIF_PKT_MAX      4096
#define  CLIB_NAME_MAX       32

typedef enum CLIB_NETIF_TYPE 
{
    CLIB_NETIF_TYPE_DPDK,
    CLIB_NETIF_TYPE_NETMAP,
} netif_type_t;

typedef enum CLIB_PKT_DIR_S 
{
    CLIB_PKT_DIR_RECV,
    CLIB_PKT_DIR_SEND,
} clib_pkt_dir_t;

typedef struct clib_netif_opt_s   netif_opt_t;

typedef struct clib_stack_netif_s stack_netif_t;

/**
 * hw相关调用函数.
 */
struct clib_netif_opt_s 
{
    // /** TODO 丰富其他接口 **/
    // /** 向dev写入数据包 **/
    // i32_t (*netif_pkt_put)(void* args,void** pkt,i32_t pkt_n);
    // /** 向dev获取数据包 **/
    // i32_t (*netif_pkt_get)(void* args,void** pkt,i32_t pkt_n);
    /** 在dev申请数据包 **/
    i32_t (*netif_pkt_malloc)(void* args,void** pkt);
    /** 在dev释放数据包 **/
    i32_t (*netif_pkt_free)(void* args,void* pkt);
    /** TODO 其他dev相关函数添加 **/
};

/**
 * hw相关定义描述.
 */
struct clib_stack_netif_s
{
    netif_type_t         type;                     /**< dev 类型 */
    u08_t                name[CLIB_NAME_MAX];      /**< dev 名称 */
    u08_t                pci[CLIB_NAME_MAX];       /**< dev pci地址 */
    u08_t                drive[CLIB_NAME_MAX];     /**< dev 驱动名称 */
    u32_t                ipv4;
    u32_t                ipv4_mask;
    u32_t                ipv4_gate;
    u16_t                ipv4_prefix;
    u16_t                ipv6_prefix;
    ipaddr_t             ipv6;
    ipaddr_t             ipv6_mask;
    ipaddr_t             ipv6_gate;
    u16_t                socket_id;
    u16_t                core_id;
    u16_t                port_id;                   /**< dev id号码 */
    u16_t                queue_id;                  /**< dev 队列号 */
    u16_t                recv_max;      
    u16_t                recv_idx;
    u16_t                send_max;
    u16_t                send_idx;
    u64_t                offload;
    void                *recv[NETIF_PKT_MAX];
    void                *send[NETIF_PKT_MAX];
    void                *args;                      /**< dev opt 回调参数 */
    netif_opt_t         *opts;                      /**< dev opt 回调函数 */
};

/**
 * 设置hw参数回调函数
 * @param netif     hw操作相关指针
 * @param opt       hw操作函数
 * @param args      hw回调操作函数
 * @return
 *   - 0    成功
 *   - -1   失败
 */
i32_t clib_netif_opt_set(stack_netif_t* netif, netif_opt_t *opt, void *args);

/**
 * 向hw写入数据包
 * @param netif     hw操作相关指针
 * @param pkt       待写入相关的数据包指针
 * @param nums      待写入相关的数据包数量
 * @return
 *   - 0    成功
 *   - -1   失败
 */
i32_t clib_netif_packet_put(stack_netif_t* netif, void** pkt, i32_t nums,clib_pkt_dir_t dir);

/**
 * 向hw获取数据包
 * @param netif     hw操作相关指针
 * @param pkt       待获取相关的数据包指针cache
 * @param nums      待获取相关的数据包最大数量
 * @return          获取的数据包数量
 */
i32_t clib_netif_packet_get(stack_netif_t* netif, void** pkt, i32_t nums,clib_pkt_dir_t dir);

/**
 * 向hw申请数据包
 * @param netif     hw操作相关指针
 * @param pkt       待获取申请的数据包指针
 * @return 
 * - 0  成功
 * - -1 失败
 */
i32_t clib_netif_packet_malloc(stack_netif_t* netif, void** pkt);

/**
 * 向hw释放数据包
 * @param netif     hw操作相关指针
 * @param pkt       待释放的数据包
 * @return
 */
void clib_netif_packet_free(stack_netif_t* netif, void* pkt);

/** TODO send tcp stack **/

#ifdef __cplusplus
}
#endif

#endif